import requests
import datetime
import random
import json
from faker import Faker
from my_app.create_photo.id_number import CalculateTime, IdNumber


def host(env):
    if env == "test":
        return "https://platform.test.zhongbaounion.com"
    elif env == "uat":
        return "https://platform.staging.zhongbaounion.com"
    else:
        raise ValueError(f"未知的环境 - {env}")


def send_request(env, method, url, params=None, data=None, json_=None, **kwargs):
    """
    发送http请求
    :param env: 环境
    :param method: 请求方法
    :param url: 地址/路径
    :param params: get请求查询字符串
    :param data: json字符串
    :param json_: python字典
    :param kwargs: 任意的关键字参数
    :return:
    """

    def header(_env):
        """生成token"""
        _url, json_data = '', ''
        if _env == "test":
            _url = f'{host(env)}/jwt/token'
            json_data = {"username": "haojinzheng", "password": "Hjz950224", "mobile": "17600732266", "systemNo": "01"}
        elif _env == "uat":
            _url = f'{host(env)}/jwt/token'
            json_data = {"username": "haojinzheng", "password": "Hjz950224@", "mobile": "17600732266", "systemNo": "01"}
        token_res = requests.post(url=_url, json=json_data).json()
        return {'access-token': token_res['token']}

    response = requests.request(method, url, params=params, data=data, json=json_, headers=header(_env=env), **kwargs)
    print(f"请求地址：{url} {method}\n请求参数：{response.request.body}\n响应结果：{response.json()}")
    return response


#  定义全局变量
t = CalculateTime(t=0)


def time_stamp():
    """返回当前时间戳"""
    return int(round(datetime.datetime.now().timestamp())) * 1000


def get_agreement_path(spu_id, env, company_id):
    """获取产品协议信息"""
    url = f'{host(env)}/api/intelligence/productInfo/getAgreementPath'
    json_data = {'companyId': f'{company_id}', 'spuId': spu_id}
    response = send_request(method="POST", url=url, json_=json_data, env=env).json()
    if response['status'] == 200:
        data = response['data']
        if data['supplierId'] == '' and data['distributorId'] == '':
            return f"产品供应商/分销商未查询到 - {data}"
        else:
            return f"查询成功-{data}"
    else:
        return str(response)


def product_sku_info(spu_id, env):
    """获取产品投保方案"""
    url = f'{host(env)}/api/product/productSku/getProductSkuInfo'
    _params = {'spuId': spu_id, 'timeStamp': time_stamp()}
    response = send_request(method="GET", url=url, params=_params, env=env)
    return [{'skuId': i['skuId'], 'skuName': i['skuName']} for i in response.json()]


def product_duty_info(spu_id, env):
    """获取产品可选责任"""
    url = f'{host(env)}/api/intelligence/insuranceop/productCheck'
    _params = {'spuId': spu_id, 'companyId': '1493473097585111040', 'timeStamp': time_stamp()}
    response = send_request(method="GET", url=url, params=_params, env=env)
    return response.json()['data']['productInfo']['productDutyList']


def order_info(pay_type, pay_period, pay_period_unit, receive_period, receive_period_unit,
               ins_period, ins_period_unit, receive_type, receive_age, age, accepted_time):
    """
    订单信息
    :param pay_type: 缴费方式
    :param pay_period: 缴费期间
    :param pay_period_unit: 缴费期间单位
    :param receive_period: 领取期间
    :param receive_period_unit: 领取期间单位
    :param ins_period: 保障期间
    :param ins_period_unit: 保障期间单位
    :param receive_type: 领取方式
    :param receive_age: 领取年龄
    :param premium 保额
    :param amount 保费
    :param age 年龄
    :param accepted_time 承保时间
    :return:
    """
    now = datetime.datetime.now()
    z = ['A', 'B', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
    json_data = {
        "orderType": "1",
        "proposalId": f"{now.strftime('%Y%m%d')}{random.randint(100000000000, 999999999999)}",
        "policyId": f"{now.strftime('%Y%m%d')}{''.join(random.sample(z, 6))}{random.randint(1000000, 9999999)}",
        "acceptedTime": str(now.strftime("%Y-%m-%d %H:%M:%S")),
        "payTime": str(now.strftime("%Y-%m-%d %H:%M:%S")),
        "payWay": "1",
        "totalPremium": '',
        "totalAmount": '',
        "applyNum": 1,
        "beginDate": str(now.strftime("%Y-%m-%d %H:%M:%S")),
        "endDate": "2999-12-31 23:59:59",
        "payType": pay_type,
        "payPeriod": pay_period,
        "payPeriodUnit": pay_period_unit,
        "receivePeriod": receive_period,
        "receivePeriodUnit": receive_period_unit,
        "insPeriod": ins_period,
        "insPeriodUnit": ins_period_unit,
        "receiveType": receive_type,
        "receiveAge": receive_age
    }
    if accepted_time != '':
        accepted_time = f"{accepted_time} 00:00:00"
        json_data['acceptedTime'], json_data['payTime'], json_data['beginDate'] = accepted_time, accepted_time, accepted_time
    if pay_period_unit == "SP":
        json_data['payPeriod'], json_data['payType'] = '', ''
    if ins_period_unit == "O":
        json_data['insPeriod'], json_data['endDate'] = '', '2999-12-31 23:59:59'
    if ins_period_unit == "Y":
        json_data['endDate'] = str(t.n_after_year(year=int(ins_period), start_year=accepted_time))
    if ins_period_unit == "A":
        _num = int(ins_period) - int(age)
        json_data['endDate'] = str(t.n_after_year(year=int(_num), start_year=accepted_time))
    return json_data


def agency_info(company_id, agency_id):
    """业务员信息"""
    return {"agencyId": str(agency_id), "companyId": str(company_id)}


def return_all_sku_name(spu_id, env):
    """返回所有的计划名称"""
    return [i['skuName'] for i in product_sku_info(spu_id, env=env)]


def return_all_duty_name(spu_id, env):
    """返回所有责任名称"""
    return [f"['{i['dutyName']}','{i['dutyId']}']" for i in product_duty_info(spu_id, env=env)]


def return_a_duty(spu_id, duty_name_list, premium, amount, env):
    """返回一个可选责任"""
    duty = product_duty_info(spu_id, env=env)
    if duty:
        if isinstance(duty_name_list, str):
            duty_name_list = eval(duty_name_list)
        duty_list = []
        for duty_name in duty_name_list:
            for n, i in enumerate(duty):
                if i['dutyName'] == duty_name:
                    duty[n]['isCheck'], duty[n]['dutyPremium'], duty[n]['dutyAmount'] = True, premium, amount
                    duty_list.append(duty[n])

        if len(duty_name_list) != len(duty_list):
            raise ValueError(f"填写的责任名称{len(duty_name_list)}个【{duty_name_list}】\n匹配成功的责任名称{len(duty_list)}个【{duty_list}】")
        if duty_list:
            return duty_list
        else:
            raise ValueError(f"填写的责任名称【{duty_name_list}】与实际的都不一致或不存在，请检查！")
    else:
        return duty


def return_a_sku(spu_id, sku_name, duty_name, premium, amount, env):
    """返回一个可选计划"""
    sku = product_sku_info(spu_id, env=env)
    if sku:
        for n, i in enumerate(sku):
            if i['skuName'] == sku_name:
                sku[n]['amount'], sku[n]['premium'] = float(amount), float(premium)
                duty = return_a_duty(spu_id, duty_name, premium * 100, amount, env=env)
                if duty_name != '' and duty:
                    sku[n]['dutyList'] = duty
                    return sku[n]
                else:
                    sku[n]['dutyList'] = []
                    return sku[n]
            else:
                raise ValueError(f"计划名称【{i['skuName']}】与填写的【{sku_name}】不一致，请检查！")
    else:
        raise KeyError(f"根据产品ID【{spu_id}】未获取到产品投保方案，请确认产品ID正确")


def product_info(spu_id, sku_name, total_premium, total_amount, sku_data):
    """
    产品信息
    """
    return {
        "spuId": spu_id,
        "spuName": sku_name,
        "totalPremium": total_premium,
        "totalAmount": total_amount,
        "portfolioSkuId": "",
        "skuList": [sku_data]
    }


def proposal_info():
    """投保人类型和是否含身故标识"""
    return {
        "policyHolderType": "1",  # 1个人  2企业
        "deathDutyFlag": ""
    }


def enterprise_info():
    """企业信息"""
    return {
        "enterpriseName": "",
        "contactsCardType": "",
        "contactsCardNo": "",
        "contactsName": "",
        "contactsMobile": "",
        "contactsEmail": ""
    }


def holder_info(id_number: str, age: str, sex: str, birthday: str):
    """
    投保人信息
    """
    fake = Faker("zh_CN")
    name = fake.name()  # 生成随机的中文名称
    return {
        "holderName": "王小飞",  # name,
        "holderMobile": f"176{random.randint(10000000, 99999999)}",
        "holderEmail": f"{random.randint(10000000, 99999999)}@qq.com",
        "holderCardType": "1",  # 证件类型
        "holderCardNo": "412728199908243197",  # id_number,
        "holderBirthday": "1999-08-24",  # birthday,
        "holderGender": "1",  # sex,
        "holderAge": "23",  # age,
        "holderIdVaildStartDate": "",
        "holderIdVaildEndDate": "",
        "holderProvinceName": "",
        "holderCityName": "",
        "holderDistrictName": "",
        "holderPostCode": ""
    }


def payment_info():
    """付款信息"""
    return {
        "payFirst": {
            "payWay": "",
            "payerAccountName": "",
            "payerAccount": "",
            "payerBankName": ""
        },
        "payRenewal": {
            "payerAccountName": "",
            "payerAccount": "",
            "payerBankName": ""
        }
    }


def insured_info():
    """被保人信息"""
    return {
        "isHolder": "1",  # 是否本人投保；1本人 0非本人
        "insuredList": [
            {
                "insuredRelation": "1",
                "insuredName": "",
                "insuredCardType": "1",
                "insuredCardNo": "",
                "insuredIdVaildStartDate": "",
                "insuredIdVaildEndDate": "",
                "insuredBirthday": "",
                "insuredGender": "",
                "insuredAge": "",
                "insuredMobile": "",
                "insuredEmail": "",
                "insuredProfessionName": "",
                "insuredProvinceName": "",
                "insuredCityName": "",
                "insuredDistrictName": "",
                "insuredAddress": "",
                "insuredPostCode": "",
                "premium": "",
                "benefitInfo": {
                    "isLegal": "1",
                    "benefitList": []
                }
            }
        ]
    }


def additional_policy(spu_id, sku_name, duty_name, pay_type, pay_period, pay_period_unit, receive_period, receive_period_unit, ins_period, ins_period_unit,
                      receive_type, receive_age, id_number, age, sex, birthday, premium, amount, env, company_id, agency_id, accepted_time):
    """
    添加保单
    """
    now = datetime.datetime.now().strftime("%H:%M:%S")
    # 计划信息
    sku_data = return_a_sku(spu_id=spu_id, sku_name=sku_name, duty_name=duty_name, premium=premium, amount=amount, env=env)

    # 总保费/总保额
    import jsonpath
    if sku_data['dutyList']:
        total_premium = float(sum(jsonpath.jsonpath(sku_data, '$..dutyPremium')) / 100)
        total_amount = float(sum(jsonpath.jsonpath(sku_data, '$..dutyAmount')))
    else:
        total_premium = premium
        total_amount = amount

    # 订单信息
    _order_info = order_info(
        pay_type=pay_type, pay_period=pay_period, pay_period_unit=pay_period_unit,
        receive_period=receive_period, receive_period_unit=receive_period_unit,
        ins_period=ins_period, ins_period_unit=ins_period_unit, age=age,
        receive_type=receive_type, receive_age=receive_age, accepted_time=accepted_time
    )
    _order_info['totalPremium'] = str(total_premium)
    _order_info['totalAmount'] = str(total_amount)
    # 投保人信息
    _holder_info = holder_info(
        id_number=id_number, sex=sex, birthday=birthday, age=age
    )
    # 产品信息
    _product_info = product_info(
        spu_id=spu_id, sku_name=sku_name, total_premium=total_premium, total_amount=total_amount, sku_data=sku_data
    )

    url = f'{host(env)}/api/intelligence/insuranceop/additionalPolicy'
    json_body = {
        'orderInfo': _order_info, 'agencyInfo': agency_info(company_id=company_id, agency_id=agency_id),
        'productInfo': _product_info, 'proposalInfo': proposal_info(),
        'enterpriseInfo': enterprise_info(), 'holderInfo': _holder_info,
        'paymentInfo': payment_info(), 'insuredInfo': insured_info()
    }
    response = send_request(method="POST", url=url, json_=json_body, env=env)
    print(f"{url}\n{str(response.request.headers)}\n{json.dumps(json_body)}\n")
    results = {'message': response.json()['message'], '保单号': json_body['orderInfo']['policyId'], '缴费期间': f"{pay_period_unit}{pay_period}",
               '保障期间': f"{ins_period_unit}{ins_period}", '领取期间': f"{receive_period_unit}{receive_period}", '领取方式': f"{receive_type}{receive_age}"}
    return results


# def read_xls(file, sheet_index=0):
#     """返回按行读取的xls文件数据，返回list"""
#     import xlrd
#     work_book = xlrd.open_workbook(file_contents=file, formatting_info=True)
#     sheet_name = work_book.sheet_by_index(sheet_index)
#     int_ls = []
#     for row in range(1, sheet_name.nrows):
#         # 将每个单元格的数据转换为字符串并加入列表
#         row_values = [str(row_value) for row_value in sheet_name.row_values(row)]
#         if row_values:
#             # 二次更新单元格数据 去除.0
#             _row_values = [row_v for row_v in row_values[:3]]
#             for j in row_values[3:]:
#                 if ".0" in j:
#                     _row_values.append(j[:-2])
#                 else:
#                     _row_values.append(j)
#             int_ls.append(_row_values)
#     return int_ls


def get_token(env):
    if env == "test":
        json_data = {
            'username': 'wangxiaofei@zhongbaounion.com',
            'password': '6XOUNt1rEGYvtHpo/duVcVRECh0xETOJUsb6Z8HFDBXVWgcX+npM6Xf2LsdA7rdUnNqIpYRl2jUlphPUlAC74e'
                        'mtAUH0gUUcTqNFspDFI7ptBkUwUjGmEfPmLJsrgVikVmWrGAuncYMVkGnbVySBL5mAwwZQNHV+df5ykLzmFZk=',
        }
        response = requests.post(f'{host(env)}/api/v2/common/login', json=json_data).json()
        data = response['data']
        return {"authorization": f"{data['tokenType']} {data['accessToken']}"}
    elif env == "uat":
        json_data = {
            'username': 'wangxiaofei@zhongbaounion.com',
            'password': 'YTy9SkHjmknl4BvCSunR4Vg0Omj1xHQSS+xyQavG1ED2iENL1buj/HE4TMUxLJ7WlHGnOp+GiK/XcLmb9lzXBl'
                        'SNqi5QJpjzVw7rm7D0hEpi96odeRTkPyx2x7eblKi+SdVoWu0yI+WwJcQ0rXIZZ6+QWzYnNlkKRVl0rANfoLI=',
        }
        response = requests.post(f'{host(env)}/api/v2/common/login', json=json_data).json()
        data = response['data']
        return {"authorization": f"{data['tokenType']} {data['accessToken']}"}


def policy_list_str(policy_id, env):
    """运营平台-查询保单"""
    url = f"{host(env)}/api/v2/ipms/newPolicyList"
    json_data = {
        'query': {
            'policyId': str(policy_id),
            'acceptedStartTime': '',
            'acceptedEndTime': '',
        },
        'policySubStatus': '',
        'page': '1',
        'pageSize': '10',
    }
    response = requests.post(url=url, headers=get_token(env=env), json=json_data).json()
    policy_uuid = response['data']['list'][0]['policyUuid']
    policy_list = str(json.dumps([{"policyUUId": f"{policy_uuid}", "policyType": 1, "refId": f"{policy_uuid}", "year": 0, "period": 0, "policyId": f"{policy_id}"}]))
    return policy_list


def submit_policy_recalc(policy_id, env):
    """保单回算"""
    import time
    url = f"{host(env)}/api/v2/ipms/submitPolicyRecalc"
    json_data = {
        'operation': 'new',
        'policyListStr': policy_list_str(policy_id=policy_id, env=env),
        'rangeCheckedArrStr': 'supplierBase,supplierOther,distributorBase,distrbutorOther,merchantBase,merchantActivity,merchantAddPeople',
        'feeValueType': '3',
        'dateTime': str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
        'recalcReason': '1',
    }
    sub_response = requests.post(url=url, headers=get_token(env), json=json_data).json()
    params = {'batchId': str(sub_response['data']['batchId'])}
    n = 0
    while True:  # 查询回算结果
        n += 1
        time.sleep(0.5)
        result_data = requests.get(f'{host(env)}/api/v2/ipms/getRecalcSumResult', params=params, headers=get_token(env)).json()['data']
        if result_data['batchStatus'] == 1 and result_data['failCount'] == 1:  # 回算失败
            css_generation_id = sub_response['data']['cssGenerationId']
            params = {'operation': 'new', 'pageIndex': '1', 'pageSize': '100', 'cssGenerationId': css_generation_id}
            fail_response = requests.get(f'{host(env)}/api/v2/ipms/getRecalcResultList', params=params, headers=get_token(env)).json()
            return {"回算失败": fail_response['data'][0]['reason']}
        elif result_data['batchStatus'] == 1 and result_data['failCount'] == 0:  # 回算成功
            return "回算成功"
        if n == 5:
            raise ValueError(f"查询{n}次仍未获取到期望结果，跳出循环，最后一次查询回算结果为：{result_data}")


def run_main(env, data_list: list, company_id, agency_id, accepted_time):
    all_message = []
    for _n in data_list:  # read_xls(file=file):
        _age, _sex = int(eval(_n[12])), int(eval(_n[13]))
        _number = t.year_first_day(int(_age))
        _id_number = IdNumber.generate_id(int(_sex), _number.replace("-", ""))
        _number_message = IdNumber(_id_number)

        message = (additional_policy(
            spu_id=_n[0], sku_name=_n[1], duty_name=_n[2], pay_period_unit=_n[3], pay_period=_n[4],
            pay_type=_n[5], ins_period_unit=_n[6], ins_period=_n[7], receive_period_unit=_n[8],
            receive_period=_n[9], receive_type=_n[10], receive_age=_n[11],
            id_number=_id_number, age=_age, sex=_sex, birthday=_number_message.get_birthday(),
            premium=float(_n[14]), amount=float(_n[15]), env=env,
            company_id=company_id, agency_id=agency_id, accepted_time=accepted_time
        ))
        _recalc = _n[16]  # 是否回算
        if _recalc == "Y":
            _recalc_res = submit_policy_recalc(policy_id=message['保单号'], env=env)
            message['回算结果'] = _recalc_res
        else:
            message['回算结果'] = "不执行保单回算"
        all_message.append(str(message))
    return all_message


if __name__ == '__main__':
    import pprint

    _spu_id = '1478966593683394560'
    _env = 'test'
    _duty_list = ['基本保险责任', '基本保险责任+重中轻症疾病额外保险金+高龄特定疾病额外保险金+恶性肿瘤扩展保险金+身故或全残保险金', '信泰附加投保人豁免保险费A款']
    # pprint.pprint(return_a_duty(
    #     spu_id=_spu_id,
    #     duty_name_list='',  # "基本保险责任+重中轻症疾病额外保险金",
    #     premium=10000,
    #     amount=10000,
    #     env=_env
    # ))
    #  20221122GREJIB8052679  成功  20221122NLKPBG8752339
    print(submit_policy_recalc(policy_id='20221122TWRJFO9328525', env=_env))
    # print(get_token(env=_env))

